package com.study.tiger.util;

import com.study.tiger.constant.MyConstant;
import com.study.tiger.pojo.JWTInfo;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;

/**
 * @Author: liutingting
 * @Date: 2022/3/3 000319:00
 * @Version: 1.0
 */
@Component
public class TokenUtil {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 生成token
     * @param jwtInfo 用户信息
     * @param expire 有效期
     * @return String
     */
    public String generateToken(JWTInfo jwtInfo, int expire) {
        String token = "";
        try {
            token = Jwts.builder()
                    .setSubject(jwtInfo.getUniqueName())
                    .claim("id", jwtInfo.getId())
                    .setExpiration(DateUtils.addSeconds(new Date(), expire))
                    .signWith(SignatureAlgorithm.RS256, getPrivateKey())
                    .compact();
        } catch (Exception e) {
            logger.error("生成token失败", e);
        }
        return token;
    }

    /**
     * 获取私钥
     * @return PrivateKey
     * @throws Exception 异常
     */
    public PrivateKey getPrivateKey() throws Exception {
        byte[] privateKeys;
        if (redisUtils.hasKey(MyConstant.REDIS_TOKEN_PRI_KEY) && redisUtils.hasKey(MyConstant.REDIS_TOKEN_PUB_KEY)) {
            privateKeys = toBytes(redisUtils.getValue(MyConstant.REDIS_TOKEN_PRI_KEY));
        } else {
            KeyPair keyPair = generateKey();
            privateKeys = keyPair.getPrivate().getEncoded();
            redisUtils.insertEver(MyConstant.REDIS_TOKEN_PRI_KEY, toHexString(privateKeys));
            redisUtils.insertEver(MyConstant.REDIS_TOKEN_PUB_KEY, toHexString(keyPair.getPublic().getEncoded()));
        }
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeys);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = kf.generatePrivate(spec);
        return privateKey;
    }

    /**
     * 生成密钥对
     * @return KeyPair
     * @throws Exception 异常
     */
    public KeyPair generateKey() throws Exception {
        String secret = "hb^A09@F2k+4T7n.wJ";
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        byte[] bytes = secret.getBytes("iso-8859-1");
        SecureRandom secureRandom = new SecureRandom(bytes);
        keyPairGenerator.initialize(1024, secureRandom);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        return keyPair;
    }

    /**
     * 字节数组转字符串
     * @param b 字节数组
     * @return String
     */
    public String toHexString(byte[] b) {
        return (new BASE64Encoder()).encodeBuffer(b);
    }

    /**
     * 字符串转字节数组
     * @param s 字符串
     * @return byte[]
     * @throws IOException IO异常
     */
    public byte[] toBytes(String s) throws IOException {
        return (new BASE64Decoder()).decodeBuffer(s);
    }
}
